package com.bilibili.juc.cf.one;

import cn.hutool.core.util.RandomUtil;

import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

/*
当发生异常时，handler也会执行，当每个handler遇到异常时继续抛出。那么程序就会以抛出异常的形式终止
 */
public class FutureHandler5Test {

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        CompletableFuture<String> orgFuture = CompletableFuture.supplyAsync(
                ()->{
                    System.out.println("supplyAsync 当前线程名称：" + Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    int count = RandomUtil.randomInt(1, 10);
                    System.out.println("随机数为: " + count);
                    if (count < 7){
                        throw new RuntimeException("第一个任务抛出了异常");
                    }
                    return "捡田螺的小男孩";
                }
        );

        CompletableFuture<String> handler1Future = orgFuture.handle((a, throwable) -> {
            System.out.println("handle1 当前线程名称：" + Thread.currentThread().getName());
            if (Objects.isNull(throwable)){
                System.out.println("上个任务执行完啦，还把 \"" + a + "\" 传过来");
                if ("捡田螺的小男孩".equals(a)) {
                    System.out.println("111");
                    return a+"==>>handler1关注了";
                }
                System.out.println("222");
                return a+"==>>handler1再考虑一下";
            }else {
                System.out.println("*** handler1处理异常信息： " + throwable.getMessage());
                throw new RuntimeException("handler1捕获到了异常，继续抛出："+throwable.getMessage());
            }
        });
        CompletableFuture<String> handler2Future = handler1Future.handle((a, throwable) -> {
            System.out.println("handle2 当前线程名称：" + Thread.currentThread().getName());
            if (Objects.isNull(throwable)){
                System.out.println("上个任务执行完啦，还把 \"" + a + "\" 传过来");
                if ("捡田螺的小男孩".equals(a)) {
                    System.out.println("333");
                    return a+"==>>handler2关注了";
                }
                System.out.println("444");
                return a+"==>>handler2再考虑一下";
            }else {
                System.out.println("*** handler2处理异常信息： " + throwable.getMessage());
                throw new RuntimeException("handler2捕获到了异常，继续抛出："+throwable.getMessage());
            }
        });

        CompletableFuture<String> result = handler2Future.exceptionally(throwable -> {
            System.out.println("*** exceptionally处理异常信息： " + throwable.getMessage());
            return "exceptionally 捕获到了异常，返回的结果信息，其中异常是：" + throwable.getMessage();
        });

        //System.out.println("handler1Future结果："+handler1Future.get());
        //System.out.println("handler2Future结果："+handler2Future.get());
        System.out.println("result结果："+result.get());
        for (int i = 0 ; i < 5;i++){
            System.out.println(" 主程序正在执行其它的任务"+i);
            TimeUnit.SECONDS.sleep(1);
        }
    }
}
/*
正常情况下：
supplyAsync 当前线程名称：ForkJoinPool.commonPool-worker-1
随机数为: 9
handle1 当前线程名称：ForkJoinPool.commonPool-worker-1
上个任务执行完啦，还把 "捡田螺的小男孩" 传过来
111
handle2 当前线程名称：ForkJoinPool.commonPool-worker-1
上个任务执行完啦，还把 "捡田螺的小男孩==>>handler1关注了" 传过来
444
result结果：捡田螺的小男孩==>>handler1关注了==>>handler2再考虑一下
 主程序正在执行其它的任务0
 主程序正在执行其它的任务1
 主程序正在执行其它的任务2
 主程序正在执行其它的任务3
 主程序正在执行其它的任务4

 异常情况下：
supplyAsync 当前线程名称：ForkJoinPool.commonPool-worker-1
随机数为: 1
handle1 当前线程名称：ForkJoinPool.commonPool-worker-1
*** handler1处理异常信息： java.lang.RuntimeException: 第一个任务抛出了异常
handle2 当前线程名称：ForkJoinPool.commonPool-worker-1
*** handler2处理异常信息： java.lang.RuntimeException: handler1捕获到了异常，继续抛出：java.lang.RuntimeException: 第一个任务抛出了异常
*** exceptionally处理异常信息： java.lang.RuntimeException: handler2捕获到了异常，继续抛出：java.lang.RuntimeException: handler1捕获到了异常，继续抛出：java.lang.RuntimeException: 第一个任务抛出了异常
result结果：exceptionally 捕获到了异常，返回的结果信息，其中异常是：java.lang.RuntimeException: handler2捕获到了异常，继续抛出：java.lang.RuntimeException: handler1捕获到了异常，继续抛出：java.lang.RuntimeException: 第一个任务抛出了异常
 主程序正在执行其它的任务0
 主程序正在执行其它的任务1
 主程序正在执行其它的任务2
 主程序正在执行其它的任务3
 主程序正在执行其它的任务4
 */
